//
//  WLFileBaseCenter.m
//  WanLian
//
//  Created by 123456 on 2018/12/7.
//  Copyright © 2018 wanlian. All rights reserved.
//

#import "WLFileBaseCenter.h"
#import "WLFileUpDownLoadModel.h"
#import "WLDataBaseManager.h"
#import "WLFileHandle.h"
//#import "MonitorFlow.h"
#import "NSString+Ext.h"
#import "LHYTimer.h"
#import "WLFileHandle.h"
#import "WLFileSocketManager.h"
#import "WLLocalNotification.h"
#define SpeedRate 1.0
@interface WLFileBaseCenter ()
@property (nonatomic, strong) LHYTimer *timer;
@property (nonatomic, assign) BOOL completeFlag;
@end

@implementation WLFileBaseCenter
#pragma mark - 定时计算发送速度
- (void)updateNetSpeed:(NSString *)netSpeed {
    dispatch_async(dispatch_get_main_queue(), ^{

        if (self.delegate && [self.delegate respondsToSelector:@selector(updateNetSpeed:withIndex:)]) {
            [self.delegate updateNetSpeed:netSpeed withIndex:self.currentTaskIndex];
        }
    });
}
- (void)startMonitor {
    if (_timer == nil) {
        WLWkSelf
        _timer = [LHYTimer timeWithTimeInterval:SpeedRate repeats:YES callBack:^{
            [weakSelf calculatenetSpeed];
        }];
    }
}
- (void)stopMonitor {
    [_timer invalidate];
    _timer = nil;
}
- (void)calculatenetSpeed {
    
    if (self.currentTaskIndex >= 0 && self.currentTaskIndex < self.totalTaskArray.count) {
        WLFileUpDownLoadModel *curModel = [self.totalTaskArray objectAtIndex:self.currentTaskIndex];
        unsigned long long totalLoadedBytes = curModel.fileTotalBytes * curModel.process;
        unsigned long long curLoadedBytes = 0;
        if (totalLoadedBytes > curModel.tempBytes) {
            curLoadedBytes = totalLoadedBytes - curModel.tempBytes;
        }
        unsigned long long netspeed = curLoadedBytes / SpeedRate;
        curModel.tempBytes = totalLoadedBytes;
        NSString *netSpeedStr = [NSString stringWithFormat:@"%@/s",[NSString formateSizeWithBytes:netspeed]];
        [self updateNetSpeed:netSpeedStr];
    }
}

- (NSArray *)getTasksArray {
    return self.totalTaskArray;
}

- (NSArray *)checkTasks:(NSArray *)tasks {
    NSMutableArray *result = [NSMutableArray array];
    
    if (tasks.count > 0) {
        for (WLFileUpDownLoadModel *model in tasks) {
            if (![self isDuplictTask:model]) {
                [result addObject:model];
            }
        }
    }
    return result;
}
- (void)showToastWithTasks:(NSArray *)tasks {
    if (tasks.count > 0) {
        NSString *message = nil;
        WLFileUpDownLoadModel *firstModel = tasks.firstObject;
        if (firstModel.isUpLoad == YES) {
            message = [NSString stringWithFormat:@"%lu个文件上传已加入传输队列！", (unsigned long)tasks.count];
        } else {
            message = [NSString stringWithFormat:@"%lu个文件下载已加入传输队列！", (unsigned long)tasks.count];
        }
        [SVProgressHUD showAndAutoCloseWithStatus:message delayTime:2.f];
    }
}

- (void)addTasks:(NSArray *)tasks {
    tasks = [self checkTasks:tasks];
//    if (<#condition#>) {
//        <#statements#>
//    }
    [self.totalTaskArray addObjectsFromArray:tasks];
    [self showToastWithTasks:tasks];
    //保存到数据库
    for (WLFileUpDownLoadModel *model in tasks) {
        [self saveTaskToDataBaseWithModel:model];
    }
    WLFileUpDownLoadModel *firstModel = tasks.firstObject;
    if (firstModel && [self isTaskCanBeStart:firstModel]) {
        [self startTaskWithModel:firstModel];
    } else {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (self.delegate && [self.delegate respondsToSelector:@selector(updateUI)]) {
                [self.delegate updateUI];
            }
        });
    }
}

- (BOOL)isDuplictTask:(WLFileUpDownLoadModel *)task {
    for (WLFileUpDownLoadModel *model in self.totalTaskArray) {
        if ([task.fileName isEqualToString:model.fileName]) {
            [SVProgressHUD showAndAutoCloseWithStatus:@"该文件已在传输队列" delayTime:2.f];
            return YES;
        }
    }
    if (task.isUpLoad == NO) {
        if ([[self queryModelWithFileName:task.fileName] count] > 0) {
            [SVProgressHUD showAndAutoCloseWithStatus:@"该文件本地已存在" delayTime:2.f];
            return YES;
        }
    }
    return NO;
}
- (void)saveTaskToDataBaseWithModel:(WLFileUpDownLoadModel *)model{
    WLDataBaseModelType modelType  = [self getModelTypeWithModel:model];
    [[WLDataBaseManager shareInstance] insertTableName:[WLFileUpDownLoadModel getTableNameWithModelType:modelType] withModel:model];
}
- (NSArray *)queryModelWithFileName:(NSString *)fileName {
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    if (fileName) {
        [dict setObject:fileName forKey:@"fileName"];
    }
    NSArray *resultArr = [[WLDataBaseManager shareInstance] queryWithTableName:[WLFileUpDownLoadModel getTableNameWithModelType:WLDataBaseModelTypeDownloaded] className:[WLFileUpDownLoadModel class] conditionDict:dict];
    return resultArr;
}
- (void)updateTaskToDataBaseWithModel:(WLFileUpDownLoadModel *)model {
    WLDataBaseModelType modelType  = [self getModelTypeWithModel:model];
    NSDictionary *dict = [self getConditiconDictWithModel:model];
    [[WLDataBaseManager shareInstance] updateTableName:[WLFileUpDownLoadModel getTableNameWithModelType:modelType] withModel:model conditionDict:dict];
}

- (void)updateTaskToDataBaseWithModel:(WLFileUpDownLoadModel *)model condictionDict:(NSDictionary *)dict {
    WLDataBaseModelType modelType  = [self getModelTypeWithModel:model];
    [[WLDataBaseManager shareInstance] updateTableName:[WLFileUpDownLoadModel getTableNameWithModelType:modelType] withModel:model conditionDict:dict];
}
- (void)deleteDataBaseWithModel:(WLFileUpDownLoadModel *)model {
    
    WLDataBaseModelType modelType  = [self getModelTypeWithModel:model];
    NSDictionary *dict = [self getConditiconDictWithModel:model];
    [[WLDataBaseManager shareInstance] deleteTableName:[WLFileUpDownLoadModel getTableNameWithModelType:modelType] withClassName:[WLFileUpDownLoadModel class] conditionDict:dict];
}
- (NSDictionary *)getConditiconDictWithModel:(WLFileUpDownLoadModel *)model {
    
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    if (model.fileName) {
        [dict setObject:model.fileName forKey:@"fileName"];
    }
    return dict;
}
- (WLDataBaseModelType)getModelTypeWithModel:(WLFileUpDownLoadModel *)model {
    WLDataBaseModelType modelType;
    BOOL isLoaded = model.loadState == FileLoadingStateComplete ? YES : NO;
    if (model.isUpLoad == YES && isLoaded == NO) {
        modelType = WLDataBaseModelTypeUpload;
    } else if (model.isUpLoad == YES && isLoaded == YES) {
        modelType = WLDataBaseModelTypeUploaded;
    } else if (model.isUpLoad == NO && isLoaded == NO) {
        modelType = WLDataBaseModelTypeDownload;
    } else {
        modelType = WLDataBaseModelTypeDownloaded;
    }
    return modelType;
}
- (void)deleteTaskWithIndexPath:(NSIndexPath *)indexPath {
    
    WLFileUpDownLoadModel *model = nil;
    self.currentTaskIndex = -1;
    if (indexPath.row < self.totalTaskArray.count) {
        model = [self.totalTaskArray objectAtIndex:indexPath.row];
    }
    if (!model) {
        return;
    }
    [self removeLocalFile:model];
    [model.dataTask cancel];
    [self.totalTaskArray removeObjectAtIndex:indexPath.row];
    if (model.loadState == FileLoadingStateFail) {
        [self checkShowCompleteAlert:model.isUpLoad];
    }
    model.loadState = FileLoadingStateDeleted;
    [self deleteDataBaseWithModel:model];
    
    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.delegate && [self.delegate respondsToSelector:@selector(didDeleteTaskWithIndexPath:)]) {
            [self.delegate didDeleteTaskWithIndexPath:indexPath];
        }
    });
    [[NSNotificationCenter defaultCenter] postNotificationName:kUpDownloadTaskCompleteNofication object:nil];
//    if (self.totalTaskArray.count > 0 && (indexPath.row < self.totalTaskArray.count - 1)) {//不是最后一个
//        WLFileUpDownLoadModel *nextModel = self.totalTaskArray[indexPath.row + 1];
//        if ([self isTaskCanBeStart:nextModel]) {
//            [self startTaskWithModel:nextModel];
//        }
//    }
}

- (void)removeLocalFile:(WLFileUpDownLoadModel *)model {
    if (model.fileURL.path.length > 0) {
        [WLFileHandle removeItemAtPath:model.fileURL.path error:nil];
    }
}
- (BOOL)isTaskCanBeStart:(WLFileUpDownLoadModel *)model {
    BOOL canStart = NO;
    if (model.loadState == FileLoadingStateWaiting || model.loadState == FileLoadingStatePause || model.loadState == FileLoadingStateFail) {
        BOOL checkResult = YES;
        for (WLFileUpDownLoadModel *model in self.totalTaskArray) {
            if (model.loadState == FileLoadingStateRunning) {
                checkResult = NO;
                break;
            }
        }
        canStart = checkResult;
    }
    return canStart;
}

- (void)pauseTaskWithIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.row >= self.totalTaskArray.count || indexPath.row < 0) {
        return;
    }
    [self stopMonitor];
    WLFileUpDownLoadModel *model = [self.totalTaskArray objectAtIndex:indexPath.row];
    model.loadState = FileLoadingStatePause;
    WLSocketWorker *dataTask = model.dataTask;
    [dataTask suspend];
    [self updateTaskToDataBaseWithModel:model];
}

- (void)continueTaskWithIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.row >= self.totalTaskArray.count || indexPath.row < 0) {
        return;
    }
    [self startMonitor];
    
    WLFileUpDownLoadModel *model = [self.totalTaskArray objectAtIndex:indexPath.row];
    if ([self isTaskCanBeStart:model]) {
        WLSocketWorker *dataTask = model.dataTask;
        if (dataTask) {
            model.loadState = FileLoadingStateRunning;
            self.currentTaskIndex = (NSInteger)[self.totalTaskArray indexOfObject:model];
            [dataTask resume];
        } else {
            [self startTaskWithModel:model];
        }
    }
    [self updateTaskToDataBaseWithModel:model];
}



- (void)dealWithProcess:(float)uploadProgress model:(WLFileUpDownLoadModel *)model {
    model.process = uploadProgress;
//    model.loadState = FileLoadingStateRunning;
    [self updateTaskToDataBaseWithModel:model];

    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.delegate && [self.delegate respondsToSelector:@selector(updateProgress:index:)]) {
            [self.delegate updateProgress:uploadProgress index:[self.totalTaskArray indexOfObject:model]];
        }
    });
}

- (void)dealWithSuccess:(NSDictionary *)successDict model:(WLFileUpDownLoadModel *)model{
    dispatch_async(dispatch_get_main_queue(), ^{
        [self stopMonitor];
//        if ([[successDict objectForKey:@"code"]integerValue] != 0) {
//            [SVProgressHUD showWithStatus:[successDict objectForKey:@"msg"]];
//            return;
//        }
        self.currentTaskIndex = -1;
        model.comleteTime = [NSString getNowStrWithFormater:@"yyyy/MM/dd HH:mm"];
        [self deleteDataBaseWithModel:model];
        model.loadState = FileLoadingStateComplete;
        [self saveTaskToDataBaseWithModel:model];
        
        NSInteger index = [self.totalTaskArray indexOfObject:model];
        WLFileUpDownLoadModel *nextModel = [self findNextModelWithIndex:index];
        [self.totalTaskArray removeObject:model];
        self.sucNum ++;
        [self checkShowCompleteAlert:model.isUpLoad];
        //    [self.uploadedArray insertObject:model atIndex:0];
        if (self.delegate && [self.delegate respondsToSelector:@selector(didCompleteTaskWithModel:)]) {
            [self.delegate didCompleteTaskWithModel:model];
        }
        
        if (nextModel && [self isTaskCanBeStart:nextModel]) {
            [self startTaskWithModel:nextModel];
        }
        
        [[NSNotificationCenter defaultCenter] postNotificationName:kUploadSuccessNofication object:nil];
        [[NSNotificationCenter defaultCenter] postNotificationName:kUpDownloadTaskCompleteNofication object:nil];
    });
    //
}
- (void)pauseCurrentTask {
    if (self.currentTaskIndex >= 0) {
        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.currentTaskIndex inSection:0];
        [self pauseTaskWithIndexPath:indexPath];
    }
}
- (void)dealWithFailure:(NSString *)errorMsg errorTag:(NSInteger)errorTag  model:(WLFileUpDownLoadModel *)model{
    dispatch_async(dispatch_get_main_queue(), ^{
        LHLog(@"dealWithFailure %@", errorMsg);
        model.loadState = FileLoadingStateFail;
        [self stopMonitor];
        self.currentTaskIndex = -1;
        NSString *message = nil;
        if (errorTag == FileTransportErrorTypeServer || errorTag == FileTransportRequestTimeOut) {
            message = errorMsg;
        } else {
            message = @"请求失败，请稍后再试";
    //        if (model.isUpLoad) {
    //            message = [NSString stringWithFormat:@"%@上传失败", model.fileName];
    //        } else {
    //            message = [NSString stringWithFormat:@"%@下载失败", model.fileName];
    //        }
        }
        [SVProgressHUD showAndAutoCloseWithStatus:message delayTime:1.f];
        
        [self checkShowCompleteAlert:model.isUpLoad];
        NSInteger index = [self.totalTaskArray indexOfObject:model];
        WLFileUpDownLoadModel *nextModel = [self findNextModelWithIndex:index];

//        [SVProgressHUD showAndAutoCloseWithStatus:message delayTime:2.f];
        if (self.delegate && [self.delegate respondsToSelector:@selector(didFailTaskWithIndex:)]) {
            [self.delegate didFailTaskWithIndex:index];
        }
    
    
        if (nextModel && [self isTaskCanBeStart:nextModel]) {
            [self startTaskWithModel:nextModel];
        }
    });
}
- (WLFileUpDownLoadModel *)findNextModelWithIndex:(NSInteger)index {
    
    WLFileUpDownLoadModel *nextModel = nil;
    if (self.totalTaskArray.count <= 1) {
        return nil;
    }
    NSInteger i = (index == self.totalTaskArray.count - 1) ? 0 : index + 1;
    while (1) {
        if (i < self.totalTaskArray.count && i >= 0) {
            if (i == index) {
                break;
            }
            WLFileUpDownLoadModel *tempModel = self.totalTaskArray[i];;
            if (tempModel.loadState == FileLoadingStateFail || tempModel.loadState == FileLoadingStatePause) {
                if (i == self.totalTaskArray.count - 1) {
                    i = 0;
                } else {
                    i ++;
                }
                continue;
            } else {
                nextModel = tempModel;
                break;
            }
        }
        break;
    }
    /*
    for (; i == index - 1; i ++) {
        if (i < self.totalTaskArray.count && i >= 0) {
            WLFileUpDownLoadModel *tempModel = self.totalTaskArray[i];;
            if (tempModel.loadState == FileLoadingStateFail || tempModel.loadState == FileLoadingStatePause) {
                if (i == self.totalTaskArray.count - 1) {
                    i = -1;
                }
                continue;
            } else {
                nextModel = tempModel;
                break;
            }
        }
        break;
    }*/
    
    return nextModel;
}
- (WLSocketWorker *)startTaskWithModel:(WLFileUpDownLoadModel *)model {return nil;}

- (WLFileUpDownLoadModel *)getCurrentTask {
    if (self.currentTaskIndex >= 0 && self.currentTaskIndex < self.totalTaskArray.count) {
        return self.totalTaskArray[self.currentTaskIndex];
    }
    return nil;
}

- (BOOL)judgeInUploadingWithFileName:(NSString *)fileName {
    for (WLFileUpDownLoadModel *model in self.totalTaskArray) {
        if ([fileName isEqualToString:model.fileName]) {
            return YES;
        }
    }
    return NO;
}
- (void)checkShowCompleteAlert:(BOOL)isUpload {
    int sucNum = self.sucNum;
    int failNum = 0;
    for (WLFileUpDownLoadModel *model in self.totalTaskArray) {
        if (model.loadState == FileLoadingStateFail) {
            failNum ++;
        }
    }
    if (failNum == self.totalTaskArray.count) {//任务全部完成
        NSString *aertStr = nil;
        if (isUpload == YES) {
            aertStr = [NSString stringWithFormat:@"上传完成，成功%d个,失败%d个！", sucNum, failNum];
        } else {
            aertStr = [NSString stringWithFormat:@"下载完成，成功%d个,失败%d个！", sucNum, failNum];
        }
        self.sucNum = 0;
        [WLLocalNotification checkCurrentNotificationStatusWithBlock:^(BOOL hasAuthor) {
            if(hasAuthor == YES) {
                [WLLocalNotification postLocalNotificationWithAlertBody:aertStr];
            } else {
                [SVProgressHUD showAndAutoCloseWithStatus:aertStr delayTime:2.f];
            }
        }];
    }
}

- (WLFileUpDownLoadModel *)findTaskModelWithName:(NSString *)fileName {
    for (WLFileUpDownLoadModel *model in self.totalTaskArray) {
        if ([model.fileName isEqualToString:fileName]) {
            return model;
        }
    }
    return nil;
}
delay_property_impl(NSMutableArray, totalTaskArray)
delay_property_impl(NSMutableArray, needUploadArray)
delay_property_impl(NSMutableArray, uploadedArray)
@end
